package cn.iocoder.yudao.framework.business.basic.enums;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * <pre>
 * OOoO0OOoO0OOOooo0oOOOO0OOOOO0oooOO0ooOOO0Ooooo0OOOOo0ooooO0OOooo0Ooooo0OOOOO
 *  枚举接口
 * OOoO0OOoO0OOOooo0oOOOO0OOOOO0oooOO0ooOOO0Ooooo0OOOOo0ooooO0OOooo0Ooooo0OOOOO
 * </pre>
 *
 * @author 山野羡民（1032694760@qq.com）
 * @see EnumValuable
 * @see cn.iocoder.yudao.framework.common.core.ArrayValuable
 */
public interface EnumCodable {

    /**
     * 枚举编码
     */
    String getCode();

    /**
     * 枚举名称
     */
    String getName();

    default boolean equalsValue(Object value) {
        return Objects.equals(getCode(), value);
    }

    default boolean equals(EnumCodable enumCodable) {
        return Objects.equals(getCode(), enumCodable.getCode())
               && Objects.equals(getName(), enumCodable.getName());
    }

    static String toString(Class<? extends EnumCodable> clazz) {
        return toVos(clazz).toString();
    }

    static List<String> toList(Class<? extends EnumCodable> clazz) {
        EnumCodable[] enumConstants = clazz.getEnumConstants();
        if (enumConstants == null) {
            return null;
        }
        return Arrays.stream(enumConstants).map(EnumCodable::getCode).toList();
    }

    static String[] toArray(Class<? extends EnumCodable> clazz) {
        return Objects.requireNonNull(toList(clazz)).toArray(String[]::new);
    }

    static List<ViewObject> toVos(EnumCodable... enumCodables) {
        if (enumCodables == null) {
            return null;
        }
        List<ViewObject> list = new ArrayList<>();
        for (EnumCodable enumCodable : enumCodables) {
            ViewObject vo = new ViewObject();
            vo.setCode(enumCodable.getCode());
            vo.setName(enumCodable.getName());
            list.add(vo);
        }
        return list;
    }

    static List<ViewObject> toVos(Class<? extends EnumCodable> clazz) {
        return toVos(clazz, new String[0]);
    }

    static List<ViewObject> toVos(Class<? extends EnumCodable> clazz, String... excludes) {
        EnumCodable[] enumConstants = clazz.getEnumConstants();
        if (enumConstants == null) {
            return null;
        }
        List<ViewObject> list = new ArrayList<>();
        for (EnumCodable enumCodable : enumConstants) {
            if (excludes != null && Arrays.asList(excludes).contains(enumCodable.getCode())) {
                continue;
            }
            ViewObject vo = new ViewObject();
            vo.setCode(enumCodable.getCode());
            vo.setName(enumCodable.getName());
            list.add(vo);
        }
        return list;
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    class ViewObject {
        private String code;
        private String name;
    }

}
